﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace Emit.Test
{
    public interface TInterface
    {
        public void Name();
    }
    public class BaseDynamicProxy
    {

        public void Invoke()
        {
            Console.WriteLine("Invoke");
            // return targetMethod.Invoke(this, args);
           // return null;
        }

    }



    public static class MyDynamicProxy
    {
        public static T CreateIntercepted<T>()
        {
            var interfaceType = typeof(T);
            var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("MyTest"), AssemblyBuilderAccess.Run);
            var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyTest");
            var typeBuilder = moduleBuilder.DefineType("ClassA", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit);
            typeBuilder.AddInterfaceImplementation(interfaceType);
            typeBuilder.SetParent(typeof(BaseDynamicProxy));
            MethodInfo[] misInterface = interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            CreateMethod<T>(typeBuilder, misInterface);
            Type personType = typeBuilder.CreateType();
            return (T)Activator.CreateInstance(personType);
        }

        public static void CreateMethod<T>(TypeBuilder typeBuilder, MethodInfo[] misInterface)
        {
            foreach (var item in misInterface)
            {
                //实现方法
                MethodBuilder mbIM = typeBuilder.DefineMethod(item.Name,
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
                    item.ReturnType,
                    item.GetParameters()?.Select(c => c.ParameterType).ToArray()
                    );

                ILGenerator il = mbIM.GetILGenerator();
                //定义一个字符串
                il.Emit(OpCodes.Ldstr, "生成的第一个程序");
                //调用一个函数
                il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
                //返回到方法开始（返回）
                il.Emit(OpCodes.Ret);

                il.Emit(OpCodes.Call, typeof(BaseDynamicProxy).GetMethod("Invoke", new Type[] {  }));
                il.Emit(OpCodes.Ret);

                typeBuilder.DefineMethodOverride(mbIM, item);
            }
        }
    }

}
